home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / find.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-26  |  9.6 KB  |  444 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     find.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #ifdef __MWERKS__            // Get the appropriate A4 stuff
  16. #include <A4Stuff.h>
  17. #else
  18. #include <SetUpA4.h>
  19. #endif
  20.  
  21. #include "nshc.h"
  22. #include "walk_utl.h"
  23.  
  24. #include "arg_utl.proto.h"
  25. #include "buf_utl.proto.h"
  26. #include "nshc_utl.proto.h"
  27. #include "str_utl.proto.h"
  28. #include "fss_utl.proto.h"
  29. #include "walk_utl.proto.h"
  30.  
  31. /* ======================================== */
  32.  
  33. #define    MAX_RULES 10
  34.  
  35. // define the types of search rules
  36.  
  37. typedef enum { rule_none,
  38.                rule_name,
  39.                rule_type,
  40.                rule_creator,
  41.                rule_and,
  42.                rule_or,
  43.                rule_files_only,
  44.                rule_dirs_only } t_rules;
  45.  
  46. // define the walking states
  47.  
  48. typedef enum { ws_none, ws_init, ws_next } t_walks;
  49.  
  50. // data definition - this struct is the root of all data
  51.  
  52. typedef struct {
  53.  
  54.     short        got_fss;                    // 0 if FSSpec calls are not available
  55.     short        arg;                        // position in arg list
  56.     t_walks        walk_state;                    // interal walk state
  57.     
  58.     t_walk_hndl    wData;                        // storage for the walk structure
  59.     
  60.     short        rule_count;                    // number of rules in arg list
  61.     short        rules[ MAX_RULES ];            // rule array
  62.     Str255        patterns[ MAX_RULES ];        // pattern array
  63.     OSType        ostypes[ MAX_RULES ];        // OS Type array
  64.  
  65. } t_find_data;
  66.  
  67. typedef    t_find_data    **t_find_hndl;
  68.  
  69. /* ======================================== */
  70.  
  71. // local prototypes
  72.  
  73. OSErr find_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  74. OSErr find_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  75. OSErr find_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  76. OSErr find_add_rule( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls , short rule, short arg );
  77. OSErr find_get_OSType(t_nshc_parms *nshc_parms, int arg, OSType *os_type);
  78. OSErr find_init( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_find_hndl fData );
  79. OSErr find_next( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_find_hndl fData );
  80.  
  81. /* ======================================== */
  82.  
  83. OSErr find_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  84. {
  85.     short        arg;
  86.     short        usage;
  87.     OSErr        error;
  88.     FSSpec        fss;
  89.     Str255        temp_str;
  90.     t_find_hndl fData;
  91.  
  92.     // get data space
  93.  
  94.     fData = (t_find_hndl)NewHandleClear( sizeof( t_find_data ) );
  95.  
  96.     if (!fData) {
  97.         nshc_calls->NSH_putStr_err( "\pfind: Could not allocate data.\r" );
  98.         nshc_parms->action = nsh_stop;
  99.         return( -1 );
  100.         }
  101.     
  102.     (**fData).got_fss = fss_test();                // test if we can use FSSpec calls
  103.     (**fData).arg = 1;                            // start at the arg = 1 position
  104.     (**fData).walk_state = ws_init;                // start by initing a searchrule_
  105.  
  106.     nshc_parms->data = (Handle)fData;
  107.     
  108.     // set up parameters
  109.     
  110.     usage = 0;
  111.         
  112.     arg = 1;
  113.     
  114.     while ( arg < nshc_parms->argc ) {
  115.     
  116.         usage = arg_to_str( nshc_parms, nshc_calls, arg, temp_str );
  117.         
  118.         if (usage) break;
  119.         
  120.         if ( pStrEqual( temp_str, "\p-name" ) )
  121.             usage = find_add_rule( nshc_parms, nshc_calls, rule_name, arg );
  122.         else
  123.         if ( pStrEqual( temp_str, "\p-type" ) ) 
  124.             usage = find_add_rule( nshc_parms, nshc_calls, rule_type, arg );
  125.         else
  126.         if ( pStrEqual( temp_str, "\p-creator" ) )
  127.             usage = find_add_rule( nshc_parms, nshc_calls, rule_creator, arg );
  128.         else
  129.         if ( pStrEqual( temp_str, "\p-a" ) ) 
  130.             usage = find_add_rule( nshc_parms, nshc_calls, rule_and, arg );
  131.         else
  132.         if ( pStrEqual( temp_str, "\p-o" ) )
  133.             usage = find_add_rule( nshc_parms, nshc_calls, rule_or, arg );
  134.         else
  135.         if ( pStrEqual( temp_str, "\p-f" ) )
  136.             usage = find_add_rule( nshc_parms, nshc_calls, rule_files_only, arg );
  137.         else
  138.         if ( pStrEqual( temp_str, "\p-d" ) )
  139.             usage = find_add_rule( nshc_parms, nshc_calls, rule_dirs_only, arg );
  140.         else
  141.             arg++;
  142.             
  143.         if (usage) break;
  144.         
  145.         }
  146.     
  147.     if ( nshc_parms->argc == 1 )
  148.         usage = 1;
  149.  
  150.     if (usage) {
  151.         nshc_calls->NSH_putStr_err( "\pUsage: find pathname [options]\r" );
  152.         nshc_parms->action = nsh_stop;
  153.         return( error );
  154.         }
  155.     
  156.     // set up walk library
  157.     
  158.     nshc_parms->action = nsh_continue;
  159. }
  160.  
  161. /* ======================================== */
  162.  
  163. OSErr find_add_rule( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls , short rule, short arg )
  164. {
  165.     short        usage;
  166.     short        shift;
  167.     short        new_arg;
  168.     short        rule_no;
  169.     t_find_hndl fData;
  170.     
  171.     fData = (t_find_hndl)nshc_parms->data;
  172.     
  173.     rule_no = (**fData).rule_count;
  174.     
  175.     (**fData).rules[ rule_no ] = rule;
  176.     
  177.     switch ( rule ) {
  178.         case rule_name:
  179.             usage = arg_to_str( nshc_parms, nshc_calls, arg+1, (**fData).patterns[rule_no] );
  180.             shift = 2;
  181.             break;
  182.         case rule_type:
  183.         case rule_creator:
  184.             usage = find_get_OSType( nshc_parms, arg+1, &(**fData).ostypes[rule_no] );
  185.             shift = 2;
  186.             break;
  187.         default:
  188.             shift = 1;
  189.         }
  190.         
  191.     new_arg = arg + shift;
  192.     
  193.     while ( new_arg < nshc_parms->argc ) {
  194.         nshc_parms->argv[ arg ] = nshc_parms->argv[ new_arg ];
  195.         arg++;
  196.         new_arg++;
  197.         }
  198.         
  199.     nshc_parms->argc -= shift;
  200.  
  201.     (**fData).rule_count = rule_no + 1;
  202.     
  203.     return( usage );
  204. }
  205.  
  206. /* ======================================== */
  207.  
  208. OSErr find_get_OSType(t_nshc_parms *nshc_parms, int arg, OSType *os_type)
  209. {
  210.     char    c;
  211.     char    *p;
  212.     int        i;
  213.     int        error;
  214.     
  215.     if (arg >= nshc_parms->argc)
  216.         return(1);
  217.     
  218.     error = 0;
  219.     *os_type = 0;
  220.     
  221.     p = &nshc_parms->arg_buf[ nshc_parms->argv[ arg ] ];
  222.     
  223.     for (i = 0 ; i < 4 ; i++ )
  224.         if ( c = *p++ ) {
  225.             *os_type = *os_type << 8;
  226.             *os_type = *os_type + c;
  227.             }
  228.         else
  229.             error = 1;
  230.             
  231.     if (*p) error = 1;
  232.     
  233.     return(error);
  234. }
  235.     
  236. /* ======================================== */
  237.  
  238. OSErr find_init( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_find_hndl fData )
  239. {
  240.     OSErr        result;
  241.     FSSpec        fss;
  242.     t_walk_hndl wData;
  243.     
  244.     if ( (**fData).arg >= nshc_parms->argc ) {
  245.         nshc_parms->action = nsh_stop;
  246.         return( 0 );
  247.         }
  248.  
  249.     result = arg_to_real_fss( nshc_parms, nshc_calls, (**fData).arg, &fss );
  250.  
  251.     (**fData).arg++;
  252.     
  253.     if (result) {
  254.         nshc_parms->action = nsh_stop;
  255.         return( -1 );
  256.         }
  257.     
  258.     wData = walk_init( &fss );
  259.     
  260.     if ( !wData ) {
  261.         nshc_calls->NSH_putStr_err( "\pfind: Could not init Walk Library.\r" );
  262.         nshc_parms->action = nsh_stop;
  263.         return( -1 );
  264.         }
  265.  
  266.     (**fData).wData = wData;
  267.     (**fData).walk_state = ws_next;
  268. }
  269.  
  270. /* ======================================== */
  271.  
  272. OSErr find_next( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_find_hndl fData )
  273. {
  274.     short        i;
  275.     short        match;
  276.     short        rule;
  277.     short        level;
  278.     short        isDir;
  279.     FSSpec        fss;
  280.     OSErr        error;
  281.     t_walk_hndl wData;
  282.     FInfo        fndrInfo;
  283.     
  284.     wData = (**fData).wData;
  285.     
  286.     if ( !wData ) {
  287.         nshc_calls->NSH_putStr_err( "\pfind: Missing data.\r" );
  288.         nshc_parms->action = nsh_stop;
  289.         return( -1 );
  290.         }
  291.  
  292.     error = walk_next( wData, &fss, &level, &isDir );
  293.     
  294.     if (error) {
  295.         (**fData).walk_state = ws_init;
  296.         DisposeHandle( wData );
  297.         (**fData).wData = 0L;
  298.         return( 0 );
  299.         }
  300.  
  301.     match = 1;
  302.  
  303.     for ( rule = 0 ; rule < (**fData).rule_count; rule++ )
  304.         switch ( (**fData).rules[ rule ] ) {
  305.             case rule_name:
  306.                 switch ( nshc_calls->NSH_match( (**fData).patterns[rule], fss.name ) ) {
  307.                     case 0:
  308.                         break;
  309.                     case 1:
  310.                         match = 0;
  311.                         break;
  312.                     default:
  313.                         nshc_calls->NSH_putStr_err( "\pfind: Bad Pattern.\r" );
  314.                         nshc_parms->action = nsh_stop;
  315.                         return( -1 );
  316.                     }
  317.                 break;
  318.             case rule_type:
  319.                 fss_GetFInfo((**fData).got_fss, &fss, &fndrInfo);
  320.                 if (fndrInfo.fdType != (**fData).ostypes[rule] )
  321.                     match = 0;
  322.                 break;
  323.             case rule_creator:
  324.                 fss_GetFInfo((**fData).got_fss, &fss, &fndrInfo);
  325.                 if (fndrInfo.fdCreator != (**fData).ostypes[rule] )
  326.                     match = 0;
  327.                 break;
  328.             case rule_and:
  329.                 if ( !match )
  330.                     rule = 1000;
  331.                 break;
  332.             case rule_or:
  333.                 if ( match )
  334.                     rule = 1000;
  335.                 else
  336.                     match = 1;
  337.                 break;
  338.             case rule_files_only:
  339.                 if ( isDir )
  340.                     match = 0;
  341.                 break;
  342.             case rule_dirs_only:
  343.                 if ( !isDir )
  344.                     match = 0;
  345.                 break;
  346.             }
  347.  
  348.     if (match) {
  349.         buf_init( nshc_calls );
  350.         for ( i = 1 ; i <= level; i++ ) {
  351.             buf_putStr( (**wData).levels[i].fss.name );
  352.             buf_putchar( ':' );
  353.             }
  354.         buf_putStr( fss.name );
  355.         buf_putchar( '\r' );
  356.         buf_flush();
  357.         }
  358.  
  359.     return(0);
  360. }
  361.  
  362.     
  363. /* ======================================== */
  364.  
  365. OSErr find_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  366. {
  367.     OSErr        result;
  368.     t_find_hndl fData;
  369.  
  370.     fData = (t_find_hndl)nshc_parms->data;
  371.  
  372.     if ( !fData ) {
  373.         nshc_calls->NSH_putStr_err( "\pfind: Missing data.\r" );
  374.         nshc_parms->action = nsh_stop;
  375.         return( -1 );
  376.         }
  377.  
  378.     if ( (**fData).walk_state == ws_init )
  379.         result = find_init( nshc_parms, nshc_calls, fData );
  380.     else
  381.         result = find_next( nshc_parms, nshc_calls, fData );
  382.         
  383.     return( result );
  384. }
  385.  
  386. /* ======================================== */
  387.  
  388. OSErr find_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  389. {
  390.     t_find_hndl fData;
  391.     t_walk_hndl wData;
  392.  
  393.     fData = (t_find_hndl)nshc_parms->data;
  394.     wData = (**fData).wData;
  395.  
  396.     if (fData)
  397.         DisposeHandle( fData );
  398.  
  399.     if (wData)
  400.         DisposeHandle( wData );
  401.  
  402.     nshc_parms->action = nsh_idle;
  403. }
  404.  
  405. /* ======================================== */
  406.  
  407. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  408. {
  409. #ifdef __MWERKS__
  410.     long oldA4  = SetCurrentA4();
  411. #else
  412.     RememberA0();
  413.     SetUpA4();
  414. #endif
  415.     
  416.     if (!nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) {
  417.     
  418.          // otherwise, handle requests from the application
  419.     
  420.           switch (nshc_parms->action) {
  421.             case nsh_start:
  422.                 nshc_parms->result = find_start( nshc_parms, nshc_calls );
  423.                 break;
  424.             case nsh_continue:
  425.                 nshc_parms->result = find_continue( nshc_parms, nshc_calls );
  426.                 break;
  427.             case nsh_stop:
  428.                 nshc_parms->result = find_stop( nshc_parms, nshc_calls );
  429.                 break;
  430.             default:
  431.                 nshc_parms->result = NSHC_NO_ERR;
  432.                 nshc_parms->action = nsh_idle;
  433.                 break;
  434.             }
  435.         
  436.         }
  437.         
  438. #ifdef __MWERKS__
  439.     SetA4(oldA4);
  440. #else
  441.     RestoreA4();
  442. #endif
  443. }
  444.